package com.ms.auction.auth.oauth2.config;

import com.ms.auctioin.common.auth.util.PermitAllUrl;
import com.ms.auction.auth.oauth2.filter.PhoneLoginAuthenticationFilter;
import com.ms.auction.auth.oauth2.filter.QrLoginAuthenticationFilter;
import com.ms.auction.auth.oauth2.handler.MyAuthenctiationFailureHandler;
import com.ms.auction.auth.oauth2.handler.MyAuthenticationSuccessHandler;
import com.ms.auction.auth.oauth2.provider.PhoneAuthenticationProvider;
import com.ms.auction.auth.oauth2.provider.QrAuthenticationProvider;
import com.ms.auction.auth.oauth2.service.PhoneUserDetailService;
import com.ms.auction.auth.oauth2.service.QrUserDetailService;
import com.ms.auction.auth.oauth2.service.UsernameUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * spring security配置
 * 
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private UsernameUserDetailService usernameUserDetailService;

	@Autowired
	private PhoneUserDetailService phoneUserDetailService;

	@Autowired
	private QrUserDetailService qrUserDetailService;


	@Autowired
	private MyAuthenctiationFailureHandler myAuthenctiationFailureHandler;

	@Autowired
	private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

	@Autowired
	private BCryptPasswordEncoder passwordEncoder;

	/**
	 * 全局用户信息<br>
	 * 方法上的注解@Autowired的意思是，方法的参数的值是从spring容器中获取的<br>
	 * 即参数AuthenticationManagerBuilder是spring中的一个Bean
	 *
	 * @param auth 认证管理
	 * @throws Exception 用户认证异常信息
	 */
/*
	@Autowired
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(usernameUserDetailService).passwordEncoder(passwordEncoder);
	}
*/

	/**
	 * 用户验证
	 * @param auth
	 */
	@Override
	public void configure(AuthenticationManagerBuilder auth) {
		auth.authenticationProvider(phoneAuthenticationProvider());
/*		auth.authenticationProvider(daoAuthenticationProvider());
		auth.authenticationProvider(qrAuthenticationProvider());*/
	}

	/**
	 * 认证管理
	 * 
	 * @return 认证管理对象
	 * @throws Exception
	 *             认证异常信息
	 */
	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Bean
	public DaoAuthenticationProvider daoAuthenticationProvider(){
		DaoAuthenticationProvider provider1 = new DaoAuthenticationProvider();
		// 设置userDetailsService
		provider1.setUserDetailsService(usernameUserDetailService);
		// 禁止隐藏用户未找到异常
		//provider1.setHideUserNotFoundExceptions(false);
		// 使用BCrypt进行密码的hash
		provider1.setPasswordEncoder(passwordEncoder);
		return provider1;
	}


	@Bean
	public PhoneAuthenticationProvider phoneAuthenticationProvider(){
		PhoneAuthenticationProvider provider = new PhoneAuthenticationProvider();
		// 设置userDetailsService
		provider.setUserDetailsService(phoneUserDetailService);
		// 禁止隐藏用户未找到异常
		provider.setHideUserNotFoundExceptions(false);
		return provider;
	}

	@Bean
	public QrAuthenticationProvider qrAuthenticationProvider(){
		QrAuthenticationProvider provider = new QrAuthenticationProvider();
		// 设置userDetailsService
		provider.setUserDetailsService(qrUserDetailService);
		// 禁止隐藏用户未找到异常
		provider.setHideUserNotFoundExceptions(false);
		return provider;
	}

	/**
	 * 手机验证码登陆过滤器
	 * @return
	 */
	@Bean
	public PhoneLoginAuthenticationFilter getPhoneLoginAuthenticationFilter() {
		PhoneLoginAuthenticationFilter filter = new PhoneLoginAuthenticationFilter();
		try {
			filter.setAuthenticationManager(this.authenticationManagerBean());
		} catch (Exception e) {
			e.printStackTrace();
		}
		filter.setAuthenticationSuccessHandler( myAuthenticationSuccessHandler);
		filter.setAuthenticationFailureHandler( myAuthenctiationFailureHandler);
		return filter;
	}

	@Bean
	public QrLoginAuthenticationFilter getQrLoginAuthenticationFilter() {
		QrLoginAuthenticationFilter filter = new QrLoginAuthenticationFilter();
		try {
			filter.setAuthenticationManager(this.authenticationManagerBean());
		} catch (Exception e) {
			e.printStackTrace();
		}
		filter.setAuthenticationSuccessHandler( myAuthenticationSuccessHandler);
		filter.setAuthenticationFailureHandler( myAuthenctiationFailureHandler);
		return filter;
	}



	/**
	 * http安全配置
	 * 
	 * @param http
	 *            http安全对象
	 * @throws Exception
	 *             http安全异常信息
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.addFilterAt(getPhoneLoginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
				//.addFilterAt(getQrLoginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
				.authorizeRequests()
				.antMatchers(PermitAllUrl.permitAllUrl()).permitAll() // 放开权限的url
				.and().authorizeRequests()
				.antMatchers("/login/phoneLogin","/login/qrLogin").permitAll()
				.and().formLogin().loginPage("/login").permitAll()
				.and().authorizeRequests()
				 .anyRequest().authenticated().and()
				//.httpBasic().and()
				.csrf().disable();
	}

}